package hust.rpc.handler;

import hust.rpc.constants.Constants;
import hust.rpc.pojo.Host;
import hust.rpc.pojo.Message;
import hust.rpc.pojo.RpcRequest;
import hust.rpc.pojo.RpcResponse;
import hust.rpc.invoker.LocalInvoker;
import hust.rpc.invoker.RemoteInvoker;
import hust.rpc.utils.SingletonUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.net.InetSocketAddress;

public class RpcInvokeHandler extends SimpleChannelInboundHandler<Message> {

    private static final Logger logger = LogManager.getLogger(RpcInvokeHandler.class);

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("通道连接: {}", ctx);
        super.channelActive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
        if (msg.getMessageType() == Constants.REQUEST_TYPE) {
            RpcRequest request = (RpcRequest) msg.getData();
            handleInvoke(ctx.channel(), request);
        } else if (msg.getMessageType() == Constants.RESPONSE_TYPE) {
            RpcResponse response = (RpcResponse) msg.getData();
            handleResponse(ctx.channel(), response);
        } else if (msg.getMessageType() == Constants.HEARTBEAT_REQUEST_TYPE) {
            handleHeartRequest(ctx.channel());
        } else if (msg.getMessageType() == Constants.HEARTBEAT_RESPONSE_TYPE) {
            handleHeartResponse(ctx.channel());
        } else {
            logger.warn("收到未知类型消息: {}", msg);
        }
    }

    protected void handleHeartResponse(Channel channel) {

    }

    protected void handleHeartRequest(Channel channel) {

    }

    /**
     * 处理响应
     */
    protected void handleResponse(Channel channel, RpcResponse response) {
        InetSocketAddress remoteAddress = (InetSocketAddress) channel.remoteAddress();
        SingletonUtils.getInstance(RemoteInvoker.class).complete(new Host(remoteAddress.getAddress().getHostAddress(), remoteAddress.getPort()), response);
    }

    /**
     * 处理请求调用
     */
    protected void handleInvoke(Channel channel, RpcRequest request) {
        logger.info("收到来自{}的请求调用{}", channel, request);
        LocalInvoker.invoke(request, channel, Constants.CODEC_KRYO);
    }
}
